var needLoadPrev = false
var needLoadNext = false
var maxWordLength = 15
var wordSeperator = " "

function setNextPage(startLine, startIndex, endLine, endIndex, text) {
    console.log("setNextPage",
                "startLine:", startLine,
                "startIndex:",startIndex,
                "endLine:",endLine,
                "endIndex:",endIndex,
                "text.length:", text.length)
    viewer.nextStartLineNumber = startLine
    viewer.nextStartIndex = startIndex
    viewer.nextEndLineNumber = endLine
    viewer.nextEndIndex = endIndex
    viewer.nextText = text
}

function setPrevPage(startLine, startIndex, endLine, endIndex, text) {
    console.log("setPrevPage",
                "startLine:", startLine,
                "startIndex:",startIndex,
                "endLine:",endLine,
                "endIndex:",endIndex,
                "text.length:", text.length)
    viewer.prevStartLineNumber = startLine
    viewer.prevStartIndex = startIndex
    viewer.prevEndLineNumber = endLine
    viewer.prevEndIndex = endIndex
    viewer.prevText = text
}

function setCurrentPage(startLine, startIndex, endLine, endIndex, text) {
    console.log("setCurrentPage",
                "startLine:", startLine,
                "startIndex:",startIndex,
                "endLine:",endLine,
                "endIndex:",endIndex,
                "text.length:", text.length)
    viewer.currentStartLineNumber = startLine
    viewer.currentStartIndex = startIndex
    viewer.currentEndLineNumber = endLine
    viewer.currentEndIndex = endIndex
    viewer.currentText = text
}

function textHeight(text) {
    return text.paintedHeight
}

function switchToPrevPage() {
    console.log("switchToPrevPage")
    getPrevPage()
    if (viewer.prevText.length > 0) {
        setCurrentFromPrev()
        //        viewerText.text = viewer.currentText
        viewerText.text = viewer.currentText
    }
    else {
        console.log("no previous page, do nothing")
    }

    //    if (needLoadPrev) {
    //        getPrevPage()
    //        needLoadPrev = false
    //    }

    //    if (viewer.prevText.length > 0) {
    //        setNextFromCurrent()
    //        setCurrentFromPrev()
    //        viewerText.text = viewer.currentText
    //        getPrevPage()
    //    }
    //    else {
    //        console.log("no previous page, do nothing")
    //    }
}

function switchToNextPage() {
    console.log("switchToNextPage")
    getNextPage()
    if (viewer.nextText.length > 0) {
        setCurrentFromNext()
        //        viewerText.text = viewer.currentText
        viewerText.text = viewer.currentText
    }
    else {
        console.log("no next page, do nothing")
    }

    //    if (needLoadNext) {
    //        getNextPage()
    //        needLoadNext = false
    //    }

    //    if (viewer.nextText.length > 0) {
    //        setPrevFromCurrent()
    //        setCurrentFromNext()
    //        viewerText.text = viewer.currentText
    //        getNextPage()
    //    }
    //    else {
    //        console.log("no next page, do nothing")
    //    }
}

function setPrevFromCurrent() {
    viewer.prevStartLineNumber = viewer.currentStartLineNumber
    viewer.prevStartIndex = viewer.currentStartIndex
    viewer.prevEndLineNumber = viewer.currentEndLineNumber
    viewer.prevEndIndex = viewer.currentEndIndex
    viewer.prevText = viewer.currentText
    console.log("setPrevFromCurrent",
                viewer.prevStartLineNumber,
                viewer.prevStartIndex,
                viewer.prevEndLineNumber,
                viewer.prevEndIndex,
                viewer.prevText.length)
}

function setCurrentFromNext() {
    viewer.currentStartLineNumber = viewer.nextStartLineNumber
    viewer.currentStartIndex = viewer.nextStartIndex
    viewer.currentEndLineNumber = viewer.nextEndLineNumber
    viewer.currentEndIndex = viewer.nextEndIndex
    viewer.currentText = viewer.nextText
    console.log("setCurrentFromNext",
                viewer.currentStartLineNumber,
                viewer.currentStartIndex,
                viewer.currentEndLineNumber,
                viewer.currentEndIndex,
                viewer.currentText.length)
    saveCurrentPosition()

}

function setCurrentFromPrev() {
    viewer.currentStartLineNumber = viewer.prevStartLineNumber
    viewer.currentStartIndex = viewer.prevStartIndex
    viewer.currentEndLineNumber = viewer.prevEndLineNumber
    viewer.currentEndIndex = viewer.prevEndIndex
    viewer.currentText = viewer.prevText
    console.log("setCurrentFromPrev",
                viewer.currentStartLineNumber,
                viewer.currentStartIndex,
                viewer.currentEndLineNumber,
                viewer.currentEndIndex,
                viewer.currentText.length)
    saveCurrentPosition()
}

function setNextFromCurrent() {
    viewer.nextStartLineNumber = viewer.currentStartLineNumber
    viewer.nextStartIndex = viewer.currentStartIndex
    viewer.nextEndLineNumber = viewer.currentEndLineNumber
    viewer.nextEndIndex = viewer.currentEndIndex
    viewer.nextText = viewer.currentText
    console.log("setNextFromCurrent",
                viewer.nextStartLineNumber,
                viewer.nextStartIndex,
                viewer.nextEndLineNumber,
                viewer.nextEndIndex,
                viewer.nextText.length)
}

function getAll() {
    console.log("get all")
    getCurrentPage()
    getNextPage()
    getPrevPage()
}

function getCurrentPage() {
    console.log("getCurrentPage input:",
                "currentStartLineNumber:",viewer.currentStartLineNumber,
                "currentStartIndex:",viewer.currentStartIndex)
    var result = new Array()
    result[0] = result[1] = result[2] = result[3] = 0
    result[4] = ""
    if (viewer.currentStartLineNumber > engine.fileLineNumber(viewer.fileName) - 1
            || viewer.currentStartLineNumber < 0) {
        console.log("ERROR::Invalid currentStartLineNumber, max is", engine.fileLineNumber(viewer.fileName) - 1)
    }
    else {
        var line = engine.getLine(viewer.fileName, viewer.currentStartLineNumber)
        if (viewer.currentStartIndex > line.length - 1
                || viewer.currentStartIndex < 0) {
            console.log("ERROR::Invalid currentStartIndex, max is", line.length - 1)
            if (viewer.currentStartIndex > line.length - 1) {
                viewer.currentStartIndex = line.length - 1
            }
            else if (viewer.currentStartIndex < 0) {
                viewer.currentStartIndex = 0
            }
        }

        var ret = getPage(viewer.currentStartLineNumber,
                          viewer.currentStartIndex,
                          viewerText.height, true)
        if (ret[4].length) {
            result = ret
        }
    }
    setCurrentPage(result[0], result[1], result[2], result[3], result[4])
    
    console.log("getCurrentPage result:",
                "currentStartLineNumber:",viewer.currentStartLineNumber,
                "currentStartIndex:",viewer.currentStartIndex,
                "startLine:", result[0],
                "startIndex:", result[1],
                "endLine:", result[2],
                "endIndex", result[3],
                "text length:",result[4].length)
}

/**
 *
 */
function getNextPage() {
    console.log("getNextPage input:",
                "currentEndLineNumber:",viewer.currentEndLineNumber,
                "currentEndIndex:",viewer.currentEndIndex)
    var lineNum
    var charIndex
    var result = new Array()
    result[0] = result[1] = result[2] = result[3] = -1
    result[4] = ""
    if (viewer.currentEndLineNumber > engine.fileLineNumber(viewer.fileName) - 1
            || viewer.currentEndLineNumber < 0) {
        console.log("ERROR::Invalid currentEndLineNumber, max is", engine.fileLineNumber(viewer.fileName) - 1)
    }
    else {
        var line = engine.getLine(viewer.fileName, viewer.currentEndLineNumber)
        if (viewer.currentEndIndex > line.length - 1
                || viewer.currentEndIndex < 0) {
            console.log("ERROR::Invalid currentEndIndex, max is", line.length - 1)
        }
        else {
            //Last char of file
            if (line.length - 1 === viewer.currentEndIndex &&
                    viewer.currentEndLineNumber === engine.fileLineNumber(viewer.fileName) - 1) {
                console.log("getNextPage result: reach the last page, do nothing")
            }
            else {
                //Last char of the line
                if (viewer.currentEndIndex === line.length - 1) {
                    //Start from the start of next line
                    lineNum = viewer.currentEndLineNumber + 1
                    charIndex = 0
                }
                else {
                    //Start from the next char
                    lineNum = viewer.currentEndLineNumber
                    charIndex = viewer.currentEndIndex + 1
                }
                var ret = getPage(lineNum,
                                  charIndex,
                                  viewerText.height, true)
                if (ret[4].length) {
                    result = ret
                }
            }
        }
    }

    setNextPage(result[0], result[1], result[2], result[3], result[4])
    console.log("getNextPage result:",
                "lineNum:",lineNum,
                "charIndex:",charIndex,
                "startLine:", result[0],
                "startIndex:", result[1],
                "endLine:", result[2],
                "endIndex", result[3],
                "text length:",result[4].length)
}


function getPrevPage() {
    console.log("getPrevPage input:",
                "currentStartLineNumber:",viewer.currentStartLineNumber,
                "currentStartIndex:",viewer.currentStartIndex)
    var lineNum = -1
    var charIndex = -1
    var result = new Array()
    result[0] = result[1] = result[2] = result[3] = -1
    result[4] = ""

    if (viewer.currentStartLineNumber > engine.fileLineNumber(viewer.fileName) - 1
            || viewer.currentStartLineNumber < 0) {
        console.log("ERROR::Invalid currentStartLineNumber, max is", engine.fileLineNumber(viewer.fileName) - 1)
    }
    else {
        var line = engine.getLine(viewer.fileName, viewer.currentStartLineNumber)
        if ((viewer.currentStartIndex > line.length - 1 &&
             line.length > 0)
                || viewer.currentStartIndex < 0) {
            console.log("ERROR::Invalid currentStartIndex, max is", line.length - 1)
        }
        else {
            //First char of file
            if (0 === viewer.currentStartLineNumber && viewer.currentStartIndex === 0) {
                console.log("getPrevPage result: reach the first page, do nothing")
            }
            else {
                //First char of line
                if (viewer.currentStartIndex === 0) {
                    //Start from last of previous line
                    lineNum = viewer.currentStartLineNumber - 1
                    line = engine.getLine(viewer.fileName, lineNum)
                    charIndex = line.length - 1
                }
                else {
                    //Start from previous char
                    lineNum = viewer.currentStartLineNumber
                    charIndex = viewer.currentStartIndex -1
                }
                var ret = getPage(lineNum,
                                  charIndex,
                                  viewerText.height, false)
                if (ret[4].length) {
                    result = ret
                }
            }
        }
    }

    setPrevPage(result[0], result[1], result[2], result[3], result[4])
    console.log("getPrevPage result:",
                "lineNum:",lineNum,
                "charIndex:",charIndex,
                "startLine:", result[0],
                "startIndex:", result[1],
                "endLine:", result[2],
                "endIndex", result[3],
                "text length:",result[4].length)
}

/**
 * Get page by start line number and start char index.
 * @param lineNum If forward is true, this is the start line number of this page
 *                     else is the last line number of this page
 * @param charIndex If forward is true, this is the start char number in the line of this page
 *                     else is the last char number in the line of this page
 * @param targetHeight The height that should be met
 * @param forward If true, means get the previous page, false get the current page
 * @return Array[0] start line number
 *         Array[1] start char index in start line
 *         Array[2] end line number
 *         Array[3] end char index in end line
 *         Array[4] page text string
 */
function getPage(lineNum, charIndex, targetHeight, forward) {
    var ret = new Array()
    //Init array
    setArray(ret, -1, -1, -1, -1, "")

    var startLineNumber
    var startCharIndex
    var endLineNumber
    var endCharIndex
    var textStr

    console.log("getPage:",
                "lineNum:", lineNum,
                "charIndex:", charIndex,
                "targetHeight", targetHeight,
                "forward:",forward)

    if (!viewer.fileLoaded) {
        console.log("file is not loaded, do nothing")
        return ret
    }

    //For safe
    if (lineNum > engine.fileLineNumber(viewer.fileName) - 1 ||
            lineNum < 0) {
        console.log("ERROR::Invalid lineNum:", lineNum,
                    "Max line number:", engine.fileLineNumber(viewer.fileName) - 1)
        return ret
    }

    //First load line's left chars
    var line = engine.getLine(viewer.fileName, lineNum)
    //For safe
    if (charIndex > line.length - 1 || charIndex < 0) {
        console.log("ERROR::Invalid charIndex:", charIndex,
                    "Max charIndex:", line.length - 1)
        if (charIndex > line.length - 1) {
            charIndex = Math.max(line.length - 1, 0)
        }
        else if (charIndex < 0) {
            charIndex = 0
        }
        console.log("Set charIndex to ", charIndex)
    }

    if (forward) {
        startLineNumber = lineNum
        startCharIndex = charIndex
    }
    else {
        endLineNumber = lineNum
        endCharIndex = charIndex
    }

    //Get rest chars of the line
    if (forward) {
//        viewerText.text = line.substring(startCharIndex)
        viewerText.text = lineSubstring(line, startCharIndex)
    }
    else {
//        viewerText.text = line.substr(0, endCharIndex+1)
        viewerText.text = lineSubstr(line, 0, endCharIndex+1)
    }

    //Last min text length that viewerText textHeight < targetHeight
    var lastMinLength = 0
    var lastMinLineLength = line.length
    while (textHeight(viewerText) <= targetHeight) {
        lastMinLength = viewerText.text.length
        lastMinLineLength = line.length
        if (forward) {
            //If line is this last line, do not get next line
            if (lineNum === engine.fileLineNumber(viewer.fileName) -  1) {
                console.log("Reaches the last line, do not load next line")
                endLineNumber = lineNum
                break
            }

            line = engine.getLine(viewer.fileName, ++lineNum)
        }
        else {
            //If line is the first one, do not get previous line
            //but continue to load following lines
            if (lineNum === 0) {
                console.log("Reaches the first line, do not load previous line,",
                            "load from 0 and forward")
                return getPage(0,0, targetHeight, true)
            }
            else {
                line = engine.getLine(viewer.fileName, --lineNum)
            }
        }

        if (forward) {
            viewerText.text += lineString(line)
        }
        else {
            viewerText.text = lineString(line) + viewerText.text
        }

        console.log("lastMinLength", lastMinLength,
                    "painted height", textHeight(viewerText),
                    "target height", targetHeight)
    }

    //At this point, the textHeight should larger than targetHeight,
    //if not then reaches the beginning/end of file
    if (textHeight(viewerText) <= targetHeight) {
        console.log("Reaches the beginning/end of file",
                    lineNum)
        if (forward) {
            setArray(ret, startLineNumber, startCharIndex,
                     endLineNumber, line.length - 1,
                     viewerText.text)
        }
        else {
            setArray(ret, 0, 0,
                     endLineNumber, endCharIndex,
                     viewerText.text)
        }
        return ret
    }

    //At this point, the textHeight is absolutely larger than height
    //Find the exact last character
    var minIndex
    var maxIndex
    var currentIndex
    if (forward) {
        //Start from lastMinLength
        minIndex = lastMinLength
        //End to the end of total text
        maxIndex = viewerText.text.length - 1
        //Add one line and this line only have one char,
        //the last line is our target
        if (minIndex === maxIndex) {
            setArray(ret, startLineNumber, startCharIndex,
                     lineNum - 1, lastMinLineLength - 1,
                     viewerText.text.substring(0, viewerText.text.length - 1))
            return ret
        }

        //Half way find index
        currentIndex = Math.floor((minIndex+maxIndex)/2)
    }
    else {
        //Start from line start
        minIndex = 0
        //End to line end
        maxIndex = line.length - 1
        //Add one line and this line only have one char,
        //the last line is our target
        if (minIndex === maxIndex) {
            setArray(ret, lineNum - 1, 0,
                     endLineNumber, endCharIndex,
                     viewerText.text.substr(1))
            return ret
        }

        //Half way find index
        currentIndex = Math.ceil((minIndex+maxIndex)/2)
    }

    var totalText = viewerText.text
    while (1) {
        if (forward) {
            viewerText.text = totalText.substring(0, currentIndex + 1)
        }
        else {
            viewerText.text = totalText.substr(currentIndex)
        }

        console.log("minIndex", minIndex,
                    "maxIndex", maxIndex,
                    "currentIndex", currentIndex,
                    "textHeight", textHeight(viewerText),
                    "targetHeight", targetHeight,
                    "currentChar", totalText.charAt(currentIndex))
        //If the textHeight is equal to targetHeight and
        //add one more char is larger than targetHeight, this is
        //what we are looking for
        if (textHeight(viewerText) === targetHeight) {
            var addedOneChar = false
            if (forward) {
                if (currentIndex < totalText.length - 1) {
                    viewerText.text += totalText.charAt(currentIndex + 1)
                    addedOneChar = true
                }
            }
            else {
                if (currentIndex > 0) {
                    viewerText.text = totalText.charAt(currentIndex - 1) + viewerText.text
                    addedOneChar = true
                }
            }
            if (addedOneChar) {
                if (textHeight(viewerText) > targetHeight) {
                    console.log("after add one more char textHeight is larger than targetHeight, found it",
                                "currentIndex", currentIndex,
                                "textHeight", textHeight(viewerText),
                                "targetHeight", targetHeight)
                    break
                }
                else {
                    //Restore
                    if (forward) {
                        viewerText.text = totalText.substring(0, currentIndex + 1)
                    }
                    else {
                        viewerText.text = totalText.substr(currentIndex)
                    }
                }
                addedOneChar = false
            }
        }

        if (textHeight(viewerText) <= targetHeight) {
            if (forward) {
                minIndex = currentIndex
                currentIndex = Math.floor((minIndex+maxIndex)/2)
            }
            else {
                maxIndex = currentIndex
                currentIndex = Math.ceil((minIndex+maxIndex)/2)
            }

            console.log("textHeight <= targetHeight,",
                        "set minIndex to current index",
                        "minIndex", minIndex,
                        "currentIndex", currentIndex,
                        "maxIndex", maxIndex)
        }
        else {
            if (forward) {
                maxIndex = currentIndex - 1
                currentIndex = Math.floor((minIndex+maxIndex)/2)
            }
            else {
                minIndex = currentIndex + 1
                currentIndex = Math.ceil((minIndex+maxIndex)/2)
            }


            console.log("textHeight > targetHeight,",
                        "set maxIndex to current index - 1",
                        "minIndex", minIndex,
                        "currentIndex", currentIndex,
                        "maxIndex", maxIndex)
        }

        if ((minIndex >= maxIndex) ||
                (forward && minIndex === currentIndex) ||
                (!forward && maxIndex === currentIndex)) {
            console.log("(minIndex >= maxIndex) ||",
                        "(forward && minIndex === currentIndex) ||",
                        "(!forward && maxIndex === currentIndex), break",
                        "minIndex", minIndex,
                        "currentIndex", currentIndex,
                        "maxIndex", maxIndex)
            break
        }
    }

    if (forward) {
        //currentIndex = lastMinLength and textHeight > targetHeight
        //means the last line's last char is the target char
        if (currentIndex === lastMinLength &&
                textHeight(viewerText) > targetHeight) {
            console.log("currentIndex === lastMinLength &&",
                        "textHeight(viewerText) > targetHeight",
                        "currentIndex", currentIndex,
                        "lastMinLength", lastMinLength,
                        "textHeight", textHeight(viewerText),
                        "targetHeight", targetHeight,
                        "set position to:",
                        "startLineNumber",startLineNumber,
                        "startCharIndex", startCharIndex,
                        "lineNum- 1", lineNum - 1,
                        "line.length - 1", line.length - 1,
                        "string:",totalText.substring(0, minIndex))
            line = engine.getLine(viewer.fileName, lineNum - 1)
            //Last line is just ok, do not need to fit word bound
            setArray(ret, startLineNumber, startCharIndex,
                     lineNum - 1, adjustLineCharIndex(line.length, line.length - 1),
                     totalText.substring(0, minIndex))
        }
        else {
            //The rest of start line is long enough
            if (lineNum === startLineNumber) {
                console.log("lineNum === startLineNumber rest line is long enough set position to:",
                            "startLineNumber",startLineNumber,
                            "startCharIndex", startCharIndex,
                            "lineNum", lineNum,
                            "currentIndex + startCharIndex", currentIndex + startCharIndex,
                            "string:", totalText.substring(0, currentIndex + 1))

                var lastWordStart = wordBoundIndex(true, totalText, currentIndex, line.length)
                if (lastWordStart == -1) {
                    //no last word, do normal set
                    setArray(ret, startLineNumber, startCharIndex,
                             lineNum, adjustLineCharIndex(line.length, currentIndex + startCharIndex),
                             totalText.substring(0, currentIndex + 1))
                }
                else {
                    //Has last word, move back to fit word bound
                    setArray(ret, startLineNumber, startCharIndex,
                             lineNum, adjustLineCharIndex(line.length, lastWordStart + startCharIndex -1),
                             totalText.substring(0, lastWordStart))
                }
            }
            else {
                console.log("currentIndex", currentIndex,
                            "lastMinLength", lastMinLength,
                            "set position to:",
                            "startLineNumber", startLineNumber,
                            "startCharIndex", startCharIndex,
                            "lineNum", lineNum,
                            "currentIndex - lastMinLength", currentIndex - lastMinLength,
                            "string:", totalText.substring(0, currentIndex + 1))
                lastWordStart = wordBoundIndex(true, totalText, currentIndex, lastMinLength)
                if (lastWordStart == -1) {
                    //no last word, do normal set
                    setArray(ret, startLineNumber, startCharIndex,
                             lineNum, adjustLineCharIndex(line.length, currentIndex - lastMinLength),
                             totalText.substring(0, currentIndex+1))
                }
                else {
                    //Has last word, move back to fit word bound
                    setArray(ret, startLineNumber, startCharIndex,
                             lineNum, adjustLineCharIndex(line.length, lastWordStart - lastMinLength - 1),
                             totalText.substring(0, lastWordStart))
                }
            }
        }
    }
    else {
        //currentIndex is line's last char and the textHeight is
        //still larger than targetHeight,
        //means the first char of last line is the target char
        if (currentIndex === line.length - 1 &&
                textHeight(viewerText) > targetHeight) {
            setArray(ret, lineNum + 1, 0,
                     endLineNumber, endCharIndex,
                     totalText.substr(currentIndex+1))
        }
        else {
            var secondWordStart = wordBoundIndex(false, totalText,
                                                 currentIndex,
                                                 line.length - 1)
            if (secondWordStart == -1) {
                //No second word, normal process
                setArray(ret, lineNum, currentIndex,
                         endLineNumber, endCharIndex,
                         totalText.substr(currentIndex))
            }
            else {
                //Fit to second word bound
                setArray(ret, lineNum, secondWordStart,
                         endLineNumber, endCharIndex,
                         totalText.substr(secondWordStart))
            }
        }
    }

    return ret
}

function adjustLineCharIndex(lineLength, charIndex) {
    //when line is not empty and charIndex is length - 2, ignore the next new line char
    if (lineLength > 0 && charIndex === lineLength - 2) {
        return lineLength - 1
    }
    else {
        return charIndex
    }
}

//word bond calculate
function wordBoundIndex(forward, totalStr, currentIndex, searchEndIndex) {
    var index = -1
    console.debug("wordBoundIndex()::",
                  "forward", forward,
                  "totalStr.length", totalStr.length,
                  "currentIndex", currentIndex,
                  "maxSearchLength", searchEndIndex)
    if (forward) {
        if (currentIndex+1 >= totalStr.length) {
            //reach the last char, do not calculate the word bound
            console.debug("reach the last char, do not calculate the word bound")
        }
        else if (totalStr[currentIndex+1] !== wordSeperator &&
                 totalStr[currentIndex] !== wordSeperator) {
            var str = totalStr.substring(0, currentIndex + 1)
            //current and next char are not space, need to calculate word bound
            var lastSpaceIndex = str.lastIndexOf(wordSeperator)
            if (lastSpaceIndex == -1) {
                //No space found, do nothing
                console.debug("No space found, do nothing")
            }
            else  {
                if (str.length - lastSpaceIndex - 1 > maxWordLength ||
                        lastSpaceIndex <= searchEndIndex) {
                    //when last word's length is too long
                    //do not found word bound
                    console.debug("last word's length is too long, do not found word bound")
                }
                else {
                    //lastSpaceIndex is not the last char,
                    //so no need to check validation
                    index = lastSpaceIndex + 1
                    var tmpStr = str.substring(searchEndIndex, index)
                    //If all string is blank do nothing
                    if (engine.isBlankString(tmpStr)) {
                        console.debug("other string is blank, do nothing")
                        index = -1
                    }
                }
            }
        }
        else {
            //No need to calculate word,
            //because the current or next char is seperator
        }
    }
    else {
        if (currentIndex === 0) {
            //reach the first char, do nothing
            console.debug("reach the first char, do not calculate the word bound")
        }
        else {
            if (totalStr[currentIndex - 1] !== wordSeperator &&
                    totalStr[currentIndex] !== wordSeperator) {
                str = totalStr.substr(currentIndex)
                var firstSpaceIndex = str.indexOf(wordSeperator)
                console.debug("firstSpaceIndex", firstSpaceIndex)
                if (firstSpaceIndex == -1) {
                    //No space found, do nothing
                    console.debug("No space found, do nothing")
                }
                else {
                    if (firstSpaceIndex > maxWordLength ||
                            firstSpaceIndex + currentIndex >= searchEndIndex) {
                        //when first word's length is too long
                        //do not found word bound
                        console.debug("first word's length is too long, do not found word bound")
                    }
                    else {
                        //Set index to the next char after seperator
                        index = firstSpaceIndex + currentIndex
                    }
                }
            }
            else {
                console.debug("current or previous char is spearator, do nothing")
            }
        }
    }
    console.debug("return index", index)
    return index
}

function setArray(array,
                  startLine, startIndex,
                  endLine, endIndex,
                  text) {
    array[0] = startLine
    array[1] = startIndex
    array[2] = endLine
    array[3] = endIndex
    array[4] = text
    console.log("setArray:",
                array[0],
                array[1],
                array[2],
                array[3],
                array[4].length)
}

function saveCurrentPosition() {
    engine.saveLastPosition(viewer.fileName, viewer.currentStartLineNumber,
                            viewer.currentStartIndex)
}

function reloadCurrentPage() {
    if (viewer.fileLoaded) {
        viewer.currentStartLineNumber = engine.lastLineNumber(viewer.fileName)
        viewer.currentStartIndex = engine.lastCharIndex(viewer.fileName)
        getCurrentPage()
        needLoadNext = true
        needLoadPrev = true
        //    viewerText.text = viewer.currentText
        viewerText.text = viewer.currentText
    }
    else {
        console.log("file is not opened do nothing")
    }
}

function saveColor() {
    console.log("color changed:", viewer.color)
    engine.setSetting(REngine.TextColor, viewer.color)
}

function saveBackgoundColor() {
    console.log("backgound changed:", viewer.backgoundColor)
    engine.setSetting(REngine.TextBackgroud, viewer.backgoundColor)
}

function saveFontSize() {
    console.log("font size changed:", viewer.fontSize)
    engine.setSetting(REngine.TextFontPixelSize, viewer.fontSize)
}

function saveLineSpace() {
    console.log("lineSpace changed:", viewer.lineSpace)
    engine.setSetting(REngine.TextLineSpace, viewer.lineSpace)
}

function saveLetterSpace() {
    console.log("letterSpace changed:", viewer.letterSpace)
    engine.setSetting(REngine.TextFontLetterSpacing, viewer.letterSpace)
}

function saveOrientation() {
    console.log("orientation changed:", screen.allowedOrientations)
    engine.setSetting(REngine.Orientation, screen.allowedOrientations)
}

function saveHeight() {
    console.log("height Changed:", height, screen.displayHeight)
    JS.reloadCurrentPage()
}

function saveSmooth() {
    console.log("smooth changed:", viewer.smooth)
    engine.setSetting(REngine.TextSmooth, viewer.smooth)
}

function saveWordSpace() {
    console.log("wordSpace changed:", viewer.wordSpace)
    engine.setSetting(REngine.TextFontWordSpacing, viewer.wordSpace)
}

function saveUnderline() {
    console.log("underLine changed:", viewer.underline)
    engine.setSetting(REngine.TextFontUnderline, viewer.underline)
}

function saveBold() {
    console.log("bold changed:", viewer.bold)
    engine.setSetting(REngine.TextFontBold, viewer.bold)
}

function saveShowToolBar() {
    console.log("showToolbar changed:", viewer.showToolBar)
    window.showToolBar = viewer.showToolBar
    engine.setSetting(REngine.ShowToolbar, viewer.showToolBar)
}

function saveAutoPageTurning() {
    console.log("Auto Page Turning changed:", viewer.autoPageTurning)
    engine.setSetting(REngine.AutoPageTurning, viewer.autoPageTurning)
}

function saveNightMode() {
    console.log("night mode changed:", viewer.nightMode)
    engine.setSetting(REngine.NightMode, viewer.nightMode)
}

function lineString(line) {
    if (engine.isBlankString(line)) {
        if (engine.setting(REngine.TextIgnoreEmptyLine)) {
            return ""
        }
    }
    return line
}

function lineSubstring(line, startIndex, endIndex) {
    if (engine.isBlankString(line)) {
        if (engine.setting(REngine.TextIgnoreEmptyLine)) {
            return ""
        }
    }

    return line.substring(startIndex, endIndex)
}

function lineSubstr(line, startIndex, length) {
    if (engine.isBlankString(line)) {
        if (engine.setting(REngine.TextIgnoreEmptyLine)) {
            return ""
        }
    }

    return line.substr(startIndex, length)
}
